package com.qiyuesuo.untils;

import com.qiyuesuo.CommFiled;
import com.qiyuesuo.common.BaseClass;
import com.qiyuesuo.enums.File_Type;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.util.Map;
import java.util.zip.GZIPInputStream;

/**
 * 用原生api写出httpClient上传和下载文件
 */
public class HttpClientUntils extends BaseClass {
    /**
     * 分隔符
     */
    private static final String BOUNDARY1 = "WebKitFormBoundary7MA4YWxkTrZu0gW ";
    private static final String PREFIX = "--";
    private static final String BOUNDARY = "WebKitFormBoundaryc9zQ3JDR9k3B5ARx";
    /**
     * 换行符
     */
    private final static String LINE_END = "\r\n";
    /**
     * 编码集
     */
    private static final String CHARSET = "utf-8";
    private static final String CONTENT_TYPE = "multipart/form-data";

    /**
     * 上传文件
     *
     * @param Url 文件上传路径
     */
    public static void createbyfile(String Url, Map<String, File> fileMap, Map<String, String> strParams) {
        try {
            //创建url请求地址
            URL url = new URL(Url);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //设置请求头信息
            conn = setPostHeader(conn);
            DataOutputStream dataOutputStream = new DataOutputStream(conn.getOutputStream());
            //写参数
            if (strParams != null) {

                dataOutputStream.writeBytes(getStrParams(strParams).toString());
            }
            if (fileMap != null) {
                //写文件
                writeFile(fileMap, dataOutputStream);
            }

            //请求结束标志
            dataOutputStream.writeBytes(PREFIX + BOUNDARY + PREFIX + LINE_END);
            dataOutputStream.flush();
            dataOutputStream.close();
            // Http响应
            InputStreamReader inputStreamReader = new InputStreamReader(conn.getInputStream());
            BufferedReader reader2 = new BufferedReader(inputStreamReader);
            //响应结果
            String responseStr = reader2.readLine();
            System.out.println("服务端响应的结果" + responseStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 下载文件
     *
     * @param s
     * @throws Exception
     */
    public static void download(String s) throws Exception {
        FileOutputStream fos = null;
        HttpURLConnection conn = null;
        try {
            //1.创建下载地址
            URL url = new URL(s);
            //2 构建连接对象
            conn = GetConnectionUntils.GetNotProxyConnection(url);
            //判断服务端正常的反馈是否已经到达了 客户端
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                //获得网络字节输入流对象
                InputStream is = conn.getInputStream();
                //建立内存到硬盘的连接
                fos = new FileOutputStream(new File(CommFiled.DOWNLOAD_DIRECTORY + System.currentTimeMillis() + File_Type.JPG.getVlaue()));
                writerFlie(is, fos);
            }
        } catch (Exception e) {
            logger.error("下载文件失败" + e.getStackTrace() + "||" + e.getMessage());
        } finally {
            CloseStreamUntils.closeStream(fos);
        }
    }

    /**
     * 读写操作
     *
     * @param inputStream
     * @param fileOutputStream
     */
    private static void writerFlie(InputStream inputStream, OutputStream fileOutputStream) {

        try {
            byte[] b = new byte[2048];
            int len = 0;
            while ((len = inputStream.read(b)) != -1) {
                fileOutputStream.write(b, 0, len);
            }
            //关闭并刷新
            fileOutputStream.flush();
        } catch (IOException e) {
            logger.error("下载文件失败" + e.getStackTrace() + "||" + e.getMessage());
        }
    }

    /**
     * s设置post请求头信息
     */
    private static HttpURLConnection setPostHeader(HttpURLConnection conn) {
        //生成时间戳
        Long timeStamp = System.currentTimeMillis();
        try {
            conn.setRequestMethod("POST");
            conn.setReadTimeout(10 * 10000000);
            conn.setConnectTimeout(10 * 10000000);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);//Post 请求不能使用缓存
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("Charset", "UTF-8");
            conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);
            conn.setRequestProperty("x-qys-open-signature", getSignature(timeStamp));
            conn.setRequestProperty("x-qys-open-accesstoken", CommFiled.ACCESS_TOKEN);
            conn.setRequestProperty("x-qys-open-timestamp", timeStamp.toString());
        } catch (ProtocolException e) {
            logger.error("请求头信息错误" + e.getMessage() + "||" + e.getStackTrace());
        }
        return conn;
    }

    /**
     * 生成签名
     *
     * @return
     */
    private static String getSignature(Long timeStamp) {
        //设置签名
        String signature = CommFiled.ACCESS_TOKEN + CommFiled.ACCESS_SECRET + timeStamp;
        return MD5Untils.getSign(signature);
        //文件上传
        /*    */
    }

    /**
     * 设置参数
     *
     * @param strParams 参数集合
     * @return
     */
    private static StringBuilder getStrParams(Map<String, String> strParams) {
        StringBuilder strSb = new StringBuilder();
        for (Map.Entry<String, String> entry : strParams.entrySet()) {
            strSb.append(PREFIX)
                    .append(BOUNDARY)
                    .append(LINE_END)
                    .append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINE_END)
                    .append("Content-Type: text/plain; charset=" + CHARSET + LINE_END)
                    .append("Content-Transfer-Encoding: 8bit" + LINE_END)
                    .append(LINE_END)
                    .append(entry.getValue())
                    .append(LINE_END);
        }
        return strSb;
    }

    /**
     * 写文件
     *
     * @param fileMap 文件集合
     * @param dos     输出流
     * @throws IOException
     */
    private static void writeFile(Map<String, File> fileMap, DataOutputStream dos) throws IOException {
        StringBuilder fileSb = new StringBuilder();
        for (Map.Entry<String, File> fileEntry : fileMap.entrySet()) {
            fileSb.append(PREFIX)
                    .append(BOUNDARY)
                    .append(LINE_END)
                    /* * 这里重点注意： name里面的值为服务端需要的key 只有这个key 才可以得到对应的文件
                     * filename是文件的名字，包含后缀名的 比如:abc.png*/
                    .append("Content-Disposition: form-data; name=\"file\"; filename=\""
                            + fileEntry.getKey() + "\"" + LINE_END)
                    .append("Content-Type: image/jpg" + LINE_END) //此处的ContentType不同于 请求头 中Content-Type
                    .append("Content-Transfer-Encoding: 8bit" + LINE_END)
                    .append(LINE_END);// 参数头设置完以后需要两个换行，然后才是参数内容
            dos.writeBytes(fileSb.toString());
            dos.flush();
            InputStream is = new FileInputStream(fileEntry.getValue());
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = is.read(buffer)) != -1) {
                dos.write(buffer, 0, len);
            }
            is.close();
            dos.writeBytes(LINE_END);
        }
    }
}
